/*
 *      xmms2-notify.c
 *      
 *      Copyright 2006 Emmanuel Beffara <manu@beffara.org>
 *      Copyright 2009 Micah Bucy <micah.bucy@gmail.com>
 *      Copyright 2009 Thomas Frauendorfer <Thomas.Frauendorfer@googlemail.com>
 *      
 *      This program is free software; you can redistribute it and/or modify
 *      it under the terms of the GNU General Public License as published by
 *      the Free Software Foundation; either version 2 of the License, or
 *      (at your option) any later version.
 *      
 *      This program is distributed in the hope that it will be useful,
 *      but WITHOUT ANY WARRANTY; without even the implied warranty of
 *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *      GNU General Public License for more details.
 *      
 *      You should have received a copy of the GNU General Public License
 *      along with this program; if not, write to the Free Software
 *      Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 *      MA 02110-1301, USA.
 */

#include <stdio.h>
#include <string.h>
#include <libnotify/notify.h>
#include <xmmsclient/xmmsclient.h>
#include <xmmsclient/xmmsclient-glib.h>
#include <glib.h>

xmmsc_connection_t *xmms = NULL;
bool firstprint = true;
GString *text = NULL;

/* Sanitize a string for HTML. {{{1 */

const struct trans {
	char c;
	const char *html;
} translation[] = {
	{ '<', "&lt;" },
	{ '>', "&gt;" },
	{ '&', "&amp;" },
	{ 0, NULL } };

void append_html (GString *buf, const char *text)
{
	while (*text) {
		const struct trans *t = translation;
		while (t->c) {
			if (t->c == *text) {
				g_string_append(buf, t->html);
				goto next;
			}
			t++;
		}
		g_string_append_c(buf, *text);
next:
		text++;
	}
}


/* Print a notification {{{1 */

void print_notify(const char *summary, GString *text, int error)
{
	NotifyNotification *not;
	GError *err = NULL;

	not = notify_notification_new(summary, text->str, NULL, NULL);
	if (error)
		notify_notification_set_urgency(not, NOTIFY_URGENCY_CRITICAL);
	notify_notification_set_timeout(not, 5000);
	if (!notify_notification_show(not, &err))
		fprintf(stderr, "error: %s\n", err->message);

	return;
}

/* Format a Medialib entry {{{1 */

int cb_medialib_entry(xmmsv_t *val, void *arg)
{
	xmmsv_t *infodict;
	int32_t current;
	int32_t tracknr;
	const char *title;
	const char *album;
	const char *artist;

	if (xmmsv_is_error(val)) {
		g_string_assign(text, xmmsv_get_error_old(val));
		print_notify("Xmms2 error", text, 1);
	}

	infodict = xmmsv_propdict_to_dict (val, NULL);
	if (!xmmsv_dict_entry_get_string(infodict, "title", &title)) {
		return 0;
	}
    xmmsv_dict_entry_get_string(infodict, "artist", &artist);
    xmmsv_dict_entry_get_string(infodict, "album", &album);
	g_string_append(text, "Artist: <b>");
	append_html(text, artist);
	g_string_append(text, "</b>\nAlbum: <b>");
	append_html(text, album);
	g_string_append(text, "</b>\n");
	if(xmmsv_dict_entry_get_int(infodict, "tracknr", &tracknr))
		g_string_append_printf(text, "[%d] ", (int)tracknr);
	g_string_append(text, "<b>");
	append_html(text, title);
	g_string_append(text, "</b>");

	print_notify("xmms2 song info...", text, 0);

	return 0;

}

/* Get the medialib entry for an id {{{1 */

int cb_current_id(xmmsv_t *val, void *arg)
{
	xmmsc_result_t *res;
	int32_t current;

	g_string_truncate(text, 0);

	if (xmmsv_is_error(val)) {
		g_string_assign(text, xmmsv_get_error_old(val));
		print_notify("Xmms2 error", text, 1);
		return 1;
	}

	xmmsv_get_int(val, &current);

	if (current == 0) {
		g_string_assign(text, "nothing playing");
		print_notify("xmms2 song info", text, 0);
		return 1;
	}

	res = xmmsc_medialib_get_info(xmms, current);
	xmmsc_result_notifier_set (res, cb_medialib_entry, xmms);
	xmmsc_result_unref (res);

	return 1;
}

int cb_status_change(xmmsv_t *val, bool *arg)
{
	xmmsc_result_t *res;
	bool passprint = *arg;

    if(passprint)
	{
		firstprint = false;
		return 1;
	}
	res = xmmsc_playback_current_id (xmms);
	xmmsc_result_notifier_set (res, cb_current_id, xmms);
	xmmsc_result_unref (res);

	return 1;
}

static void exit_notify(void *arg)
{
	GMainLoop *loop = arg;
	g_main_loop_quit(loop);
}

int main (int argc, char **argv)
{
	xmmsc_result_t *res;

	text = g_string_sized_new(256);

	notify_init("xmms2-notify");

	xmms = xmmsc_init("xmms2-notify");
	if (!xmmsc_connect(xmms, NULL)) {
		fprintf(stderr, "connection failed: %s\n", xmmsc_get_last_error(xmms));
		return 1;
	}

		GMainLoop *loop = g_main_loop_new(NULL, FALSE);
		res = xmmsc_playback_current_id (xmms);
		xmmsc_result_notifier_set (res, cb_current_id, xmms);
		xmmsc_result_unref (res);

		res = xmmsc_broadcast_playback_current_id (xmms);
		xmmsc_result_notifier_set (res, cb_current_id, xmms);
		xmmsc_result_unref (res);
		
		res = xmmsc_playback_status (xmms);
		xmmsc_result_notifier_set (res, cb_status_change, &firstprint);
		xmmsc_result_unref (res);
		
		res = xmmsc_broadcast_playback_status (xmms);
		xmmsc_result_notifier_set (res, cb_status_change, &firstprint);
		xmmsc_result_unref (res);
		
		xmmsc_disconnect_callback_set(xmms, (xmmsc_disconnect_func_t) exit_notify, loop);	

		xmmsc_mainloop_gmain_init(xmms);
		g_main_loop_run(loop);

	return 0;
}
